/*
 * Project 2 - Process Scheduler
 * Team - BitwiseGuys
 * Team members: Tyson Lewis, Josh Warner, Dallas Rosson, Ken Norton
 */

package backend;

import backend.IO.IOType;

/**
 * This class creates the various processes that will be running on the cpu. 
 * This higher lower the ordinal of the element is its priority.
 * 
 * @author Ken Norton
 *
 */
public class SchedulerProcess {
	
	/**
	 * The type of the process.
	 */
	private ProcessType my_type;
	
	/**
	 * The number of steps that the process will run before resetting to zero.
	 */
	private int my_no_steps;
	
	/**
	 * The requests that the process will make.
	 */
	private IOType my_requests[];
	
	/**
	 * The request step. This is a parallel array for the step number that the
	 * corresponding request will occur on.
	 */
	private int my_request_step[];
	
	/**
	 * The request index.
	 */
	private int my_request_index;
	
	/**
	 * These are the types of processes that will be created.
	 */
	public enum ProcessType {
		
		/**
		 * This process takes input and generates output.
		 */
		UI,
		
		/**
		 *  This process creates some value that is stored in shared memory.
		 */
		PRODUCER,
		
		/**
		 * This process reads and removes a value that is stored in shared memory.
		 */
		CONSUMER,
		
		/**
		 * This process is synched with one or more other process.
		 */
		SYNCHED,
		
		/**
		 * This process does some work in the background.
		 */
		CALCULATOR,
		
		/**
		 * This process waits at the end of the ready queue and runs when there
		 * are no other processes.
		 */
		IDLE
	}
	
	/**
	 * Main constructor.
	 * 
	 * @param the_type
	 */
	public SchedulerProcess(final ProcessType the_type, final int the_no_steps, final IOType the_requests[],
			final int the_request_steps[]) {
		my_type = the_type;
		my_no_steps = the_no_steps;
		my_requests = the_requests;
		my_request_step = the_request_steps;
		my_request_index = 0;
	}
	
	public int runProcess() {
		int value = -1;
		
		switch (my_type) {
		case UI:
			value = nextRequest().ordinal();
			break;
		case PRODUCER:
			value = (int) (Math.random() * 1000);
			break;
		case CONSUMER:
			value = 0;
			break;
		case CALCULATOR:
			 // ??? ;
			break;
		case SYNCHED:
			// Synch with other processes.
			break;
		}
		
		return value;
	}
	
	/* ************************************************
	 * Getters
	 **************************************************/
	
	/**
	 * Gets the type of the process.
	 * 
	 * @return The type of the process.
	 */
	public ProcessType getType() {
		return my_type;
	}
	
	/**
	 * Gets the number of steps that the process will run before returning to zero.
	 * @return
	 */
	public int getNoSteps() {
		return my_no_steps;
	}
	
	/**
	 * Gets the next request.
	 * 
	 * @return The specified request.
	 */
	public IOType nextRequest() {
		IOType request = null;
		
		if (my_type != ProcessType.IDLE && my_requests.length > 0) {
			request = my_requests[my_request_index];
			//  Increments the index; loops back to zero when max is reached.
			my_request_index = (my_request_index + 1) % my_requests.length;
		}
		return request;
	}
	
	/**
	 * Gets the step of the next request. This method will return the same value each time
	 * it is called until nextRequest() is called.
	 * 
	 * @return The step of the next request.
	 */
	public int getRequestStep() {
		int step = -1;
		if (my_type != ProcessType.IDLE && my_request_step.length > 0) {
			step = my_request_step[my_request_index];
		}
		return step;
	}
}
